// Custom validation rules.

$.validator.addMethod("slug", function (value) {
    return /^[A-Za-z0-9_-]*$/.test(value);
}, "Only letters, digits, hyphens and underscores please.");

$.validator.addMethod("statuscode", function (value) {
    return ($("#status_field").val() != "0") ||
        /^[0-9]{3}$/.test(value);
}, "000 to 999");

$.validator.addMethod("header", function (value) {
    // This pattern ought to match RFC 2616 section 2.2, and the corresponding
    // regex in htmock.views.inspect.
    return /^[!#\$%&'\*\+\-\.0-9@A-Z\^_`a-z]*$/.test(value);
}, "Not a valid header.");

$.validator.addMethod("headerDependency", function (value, element) {
    // Checks that this isn't an empty header name for a non-empty value.
    if (value == "") {
        valueFieldId = element.id.replace("header_field", "value_field");
        return ($("#" + valueFieldId).val() == "");
    } else {
        return true;
    }
}, "Please enter the header field name.");

var headerValidationRules = { header: true, headerDependency: true };


// Get the maximum ID a header row has.
function getMaxRowId() {
    return parseInt($("#max_header_field").val());
}

// Set the new maximum ID a header row has.
function setMaxRowId(newMax) {
    $("#max_header_field").val(newMax);
}

// Delete the header row with the specified ID.
function deleteHeaderRow(rowId) {
    $("#header_row_" + rowId).remove();
}

// Create a handler function that deletes the specified row.
function rowDeleteHandler(rowId) {
    return function () {
        deleteHeaderRow(rowId);
    }
}

// Add a new header row and return its ID.
function addHeaderRow() {
    var rowId = getMaxRowId() + 1;
    $("#headers-table > tbody").append(
        '<tr id="header_row_' + rowId + '">' +
            '<td><input type="text" id="header_field_' + rowId +
                '" name="header' + rowId + '"></td>' +
            '<td><input type="text" id="value_field_' + rowId +
                '" name="value' + rowId + '"></td>' +
            '<td class="action"><input type="button" id="delete_button_' +
                rowId + '" value="Delete"></td>' +
        '</tr>'
    );
    $("#delete_button_" + rowId).click(rowDeleteHandler(rowId));
    $("#header_field_" + rowId).autocomplete({
        source: headerNames, delay: 0
    }).focus().rules("add", headerValidationRules);
    $("#value_field_" + rowId).focus(doHeaderValueMagic);
    setMaxRowId(rowId);
    return rowId;
}

// Autocomplete the header value field; called on focus.
function doHeaderValueMagic() {
    var headerFieldId = this.id.replace("value_field", "header_field");
    var headerName = $("#" + headerFieldId).val().toLowerCase();
    
    // Setup autocompletion
    $(this).autocomplete("destroy");
    if (headerValues.hasOwnProperty(headerName)) {
        $(this).autocomplete({ source: headerValues[headerName], delay: 0 });
    }
    
    // Fill in the default value
    if (this.value == "") {
        if (headerDefaults.hasOwnProperty(headerName)) {
            this.value = headerDefaults[headerName];
            this.select();
        }
    }
}

// Load the named template.
function loadTemplate(tplName) {
    var template = templates[tplName];
    $("#status_field").val(template.status);
    $("#custom_status_field").val("");
    $("#custom_status_field").hide();
    
    var maxId = getMaxRowId();
    for (var i = 0; i <= maxId; ++i) {
        deleteHeaderRow(i);
    }
    for (var header in template.headers) {
        var rowId = addHeaderRow();
        $("#header_field_" + rowId).val(header);
        $("#value_field_" + rowId).val(template.headers[header]);
    }
    
    $("#body_field").val(template.body);
}

// Set up hiding/showing the custom status field.
function manageStatusField() {
    $("#custom_status_field").hide();
    $("#status_field").change(function () {
        if ($("#status_field").val() == 0) {
            $("#custom_status_field").show();
        } else {
            $("#custom_status_field").hide();
        }
    });
}

// Set up adding/deleting header rows.
function manageHeaderRows() {
    for (i = 0; i < 5; ++i) {
        $("#header_row_" + i).append(
            '<td class="action"><input type="button" id="delete_button_' + i +
            '" value="Delete"></td>'
        );
        $("#delete_button_" + i).click(rowDeleteHandler(i));
    }
    
    $("#headers-table").after(
        '<input type="button" id="add_header_button" value="More">'
    );
    $("#add_header_button").click(addHeaderRow);
}

// Set up validation of the form's fields.
function setupValidation() {
    $("#create_form").validate({
        rules: {
            "label": {
                slug: true
            },
            
            "ttl": {
                number: true,
                min: 0.1
            },
            
            "custom_status": {
                statuscode: true
            }
        }
    });
    
    for (i = 0; i < 5; ++i) {
        $("#header_field_" + i).rules("add", headerValidationRules);
    }
}

// Set up template loading.
function setupTemplates() {
    function clickHandler(tplName) {
        return function () {
            loadTemplate(tplName);
        }
    }
    
    $("#create_form").before(
        '<div id="template_area">Load from template: </div>'
    );
    for (var tpl in templates) {
        $("#template_area").append(
            '<input type="button" id="tpl_' + tpl + '_button" value="' +
                templates[tpl].caption + '"> '
        );
        $("#tpl_" + tpl + "_button").click(clickHandler(tpl));
    }
}

// Set up autocompletion of header names and values and of the entity body.
function setupAutocompletion() {
    var maxId = getMaxRowId();
    for (var i = 0; i <= maxId; ++i) {
        $("#header_field_" + i).autocomplete({
            source: headerNames, delay: 0
        });
        $("#value_field_" + i).focus(doHeaderValueMagic);
    }
    
    $("#body_field").focus(function () {
        if (this.value == "") {
            // Find a Content-Type header.
            var maxId = getMaxRowId();
            for (var i = 0; i <= maxId; ++i) {
                if (elementExists("header_field_" + i) &&
                    ($("#header_field_" + i).val().toLowerCase() ==
                     "content-type"))
                {
                    // Extract the actual type.
                    var type = $("#value_field_" + i).val().split(";")[0];
                    if (bodyDefaults.hasOwnProperty(type)) {
                        this.value = bodyDefaults[type];
                        this.select();
                    }
                    return;
                }
            }
        }
    });
}


$(document).ready(function () {
    manageStatusField();
    manageHeaderRows();
    setupValidation();
    setupTemplates();
    setupAutocompletion();
});
